﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.BlogCore.Message
 * 唯一标识：085fbc36-90e8-436a-9e14-7ed8ec1a24c5
 * 文件名：VampirewalMessenger
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2024/6/25 16:52:13
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

namespace Vampirewal.BlogCore;

/// <summary>
///
/// </summary>
internal partial class VampirewalMessenger
{
    private static VampirewalMessenger _instance;
    private static object _objLock = new object();

    /// <summary>
    /// 获取单例实例
    /// </summary>
    /// <returns></returns>
    public static VampirewalMessenger GetInstance()
    {
        if (_instance == null)
        {
            lock (_objLock)
            {
                if (_instance == null)
                {
                    _instance = new VampirewalMessenger();
                }
            }
        }
        return _instance;
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    public VampirewalMessenger()
    {
    }

    /// <summary>
    /// 注册消息
    /// </summary>
    public void RegistAll(IServiceProvider service)
    {
        //var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IMessageManager)))).ToArray();
        var types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.GetInterfaces().Contains(typeof(IVampirewalMessageManager))).ToArray();
        foreach (var v in types)
        {
            //object obj = Activator.CreateInstance(v);
            object obj = ActivatorUtilities.CreateInstance(service,v);
            MethodInfo[] methods = obj.GetType().GetMethods().Where(w => w.GetCustomAttribute<RegistMethodAttribute>() != null).ToArray();
            foreach (var item in methods)
            {
                RegistMethodAttribute attribute = item.GetCustomAttribute<RegistMethodAttribute>();
                if (attribute != null)
                {
                    if (attribute.Token == null)
                    {
                        GetInstance().Register(obj, item.Name, item);
                    }
                    else
                    {
                        GetInstance().Register(obj, attribute.Token, item);
                    }
                }
            }
        }
    }

    private Dictionary<string, MethodInstance> MethodInstanceDic = new Dictionary<string, MethodInstance>();

    /// <summary>
    /// 注册消息
    /// </summary>
    /// <param name="register"></param>
    /// <param name="token"></param>
    /// <param name="methodInfo"></param>
    /// <exception cref="Exception"></exception>
    public void Register(object register, string token, MethodInfo methodInfo)
    {
        MethodInstance tokenInstance = new MethodInstance();
        tokenInstance.Register = register;
        tokenInstance.MethodInfo = methodInfo;
        try
        {
            MethodInstanceDic.Add(token, tokenInstance);
        }
        catch (Exception)
        {
            throw new Exception("该Token消息已注册");
        }
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="token"></param>
    /// <param name="parameters"></param>
    /// <exception cref="Exception"></exception>
    public object Send(string token, params object[] parameters)
    {
        if (MethodInstanceDic.TryGetValue(token, out var Method))
        {
            var ParameterTypes = Method.MethodInfo.GetParameters();

            if (ParameterTypes.Length == 0 || ParameterTypes.Length > 1)
            {
                throw new Exception("参数只能有1个！");
            }

            var CurParmaeter = ParameterTypes[0];

            var data = JsonSerializer.Deserialize(parameters[0].ToString(), CurParmaeter.ParameterType);

            var validationResults = new List<ValidationResult>();
            ValidationContext validation = new ValidationContext(data);

            bool isValid = Validator.TryValidateObject(data, validation, validationResults, true);
            if (!isValid)
                throw new Exception(string.Join("\r\n", validationResults.Select(s => s.ErrorMessage)));

            return Method.MethodInfo.Invoke(Method.Register, new object[] { data });
        }

        throw new Exception("未找到该消息");
    }
}

/// <summary>
///
/// </summary>
internal class MethodInstance
{
    /// <summary>
    /// 类
    /// </summary>
    public object Register { get; set; }

    /// <summary>
    /// 方法
    /// </summary>
    public MethodInfo MethodInfo { get; set; }
}

/// <summary>
/// 注册为消息
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class RegistMethodAttribute : Attribute
{
    /// <summary>
    ///
    /// </summary>
    public RegistMethodAttribute()
    {
        //构造函数
    }

    /// <summary>
    ///
    /// </summary>
    /// <param name="token"></param>
    public RegistMethodAttribute(string token)
    {
        Token = token;
    }

    /// <summary>
    /// 标识
    /// </summary>
    public string Token { get; set; }
}

public class RequestBody
{
    public string Data { get; set; }
}